package cn.yto.print.service;

import cn.yto.print.model.request.CameraLoginRequest;
import cn.yto.print.model.request.CameraOsdRequest;
import cn.yto.print.model.response.CameraLoginResponse;
import cn.yto.print.model.response.CameraResponse;
import cn.yto.print.service.handle.HCNetSDK;
import cn.yto.print.utils.AESUtil;
import cn.yto.print.utils.CommonUtil;
import com.alibaba.fastjson.JSON;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.io.File;

@Slf4j
@Service
public class CameraDeviceService {

    private static HCNetSDK hCNetSDK = null;

    private CameraResponse loadCameraSdk() {

        CameraResponse response = new CameraResponse(CameraResponse.SUCCESS_CODE);
        if (hCNetSDK == null) {
            String strDllPath = CommonUtil.getCurrentDir("\\lib\\HCNetSDK.dll");
            File hkSdkFile = new File(strDllPath);
            if (!hkSdkFile.exists()) {
                response.setCode(CameraResponse.FAILURE_CODE);
                response.setMsg("加载 HK SDK 失败，请检查 SDK 配置路径");
                log.info(JSON.toJSONString(response));
                return response;
            }

            try {
                hCNetSDK = Native.loadLibrary(strDllPath, HCNetSDK.class);
                if (!hCNetSDK.NET_DVR_Init()) {
                    response.setCode(CameraResponse.FAILURE_CODE);
                    response.setMsg("加载 HK SDK 失败，请联系运维人员~");
                }
            } catch (Exception ex) {
                log.error("加载 HK SDK 发生异常", ex);
                response.setCode(CameraResponse.FAILURE_CODE);
                response.setMsg("加载 HK SDK 发生异常");
                return response;
            }
        }

        response.setMsg("加载 HK SDK 成功");
        log.info(JSON.toJSONString(response));
        return response;
    }

    public CameraResponse<CameraLoginResponse> login(CameraLoginRequest request) {

        CameraResponse loadSdkResp = loadCameraSdk();
        if (!CameraResponse.SUCCESS_CODE.equals(loadSdkResp.getCode())) {
            return loadSdkResp;
        }

        CameraResponse response = new CameraResponse(CameraResponse.SUCCESS_CODE);
        Integer userId;
        byte startChan = 0;

        try {
            HCNetSDK.NET_DVR_USER_LOGIN_INFO mStrLoginInfo = new HCNetSDK.NET_DVR_USER_LOGIN_INFO();
            HCNetSDK.NET_DVR_DEVICEINFO_V40 mStrDeviceInfo = new HCNetSDK.NET_DVR_DEVICEINFO_V40();

            mStrLoginInfo.sDeviceAddress = new byte[HCNetSDK.NET_DVR_DEV_ADDRESS_MAX_LEN];
            System.arraycopy(request.getIp().getBytes(), 0, mStrLoginInfo.sDeviceAddress, 0, request.getIp().length());

            mStrLoginInfo.sUserName = new byte[HCNetSDK.NET_DVR_LOGIN_USERNAME_MAX_LEN];
            System.arraycopy(request.getUserName().getBytes(), 0, mStrLoginInfo.sUserName, 0, request.getUserName().length());

            mStrLoginInfo.sPassword = new byte[HCNetSDK.NET_DVR_LOGIN_PASSWD_MAX_LEN];
            String decryptPass = AESUtil.decryptFromHex(request.getPassword()).trim();
            System.arraycopy(decryptPass.getBytes(), 0, mStrLoginInfo.sPassword, 0, decryptPass.length());

            mStrLoginInfo.wPort = (short) request.getPort();
            mStrLoginInfo.write();

            userId = hCNetSDK.NET_DVR_Login_V40(mStrLoginInfo, mStrDeviceInfo);
            if (userId < 0) {
                response.setCode(CameraResponse.FAILURE_CODE);
                response.setMsg("摄像头登录失败：" + hCNetSDK.NET_DVR_GetLastError());
                log.info(JSON.toJSONString(response));
                return response;
            }

            mStrDeviceInfo.read();
            if (mStrDeviceInfo.struDeviceV30.byChanNum > 0) {
                startChan = mStrDeviceInfo.struDeviceV30.byStartChan;
            } else if (mStrDeviceInfo.struDeviceV30.byIPChanNum > 0) {
                startChan = mStrDeviceInfo.struDeviceV30.byStartDChan;
            }

            response.setData(new CameraLoginResponse(userId, startChan));
        } catch (Exception e) {
            log.error("摄像头登录发生异常", e);
            response.setCode(CameraResponse.FAILURE_CODE);
            response.setMsg("摄像头登录发生异常");
            return response;
        }

        response.setMsg("登录成功");
        log.info(JSON.toJSONString(response));
        return response;
    }

    public CameraResponse logout(CameraOsdRequest request) {
        CameraResponse response = new CameraResponse(CameraResponse.SUCCESS_CODE);
        if (hCNetSDK != null) {
            try {
                hCNetSDK.NET_DVR_Logout(request.getCi().getUserId());
            } catch (Exception e) {
                log.error("注销摄像头发生异常", e);
                response.setCode(CameraResponse.FAILURE_CODE);
                response.setMsg("注销失败");
                return response;
            }
        }

        response.setMsg("注销成功");
        log.info(JSON.toJSONString(response));
        return response;
    }

    public CameraResponse cameraOsd(CameraOsdRequest request) {

        CameraResponse response = loadCameraSdk();
        if (!CameraResponse.SUCCESS_CODE.equals(response.getCode())) {
            return response;
        }
        if (null == request.getCi().getUserId()) {
            response.setCode(CameraResponse.FAILURE_CODE);
            response.setMsg("摄像头 OSD 失败：缺失用户ID");
            log.info(JSON.toJSONString(response));
            return response;
        }

        try {
            HCNetSDK.NET_DVR_SHOWSTRING_V30 mStrShowString = new HCNetSDK.NET_DVR_SHOWSTRING_V30();
            mStrShowString.read();
            String[] osd = request.getOi().getText().split(",");
            for (int i = 0; i < osd.length; i++) {
                mStrShowString.dwSize = mStrShowString.size();
                mStrShowString.struStringInfo[i].wShowString = 1;
                mStrShowString.struStringInfo[i].wShowStringTopLeftY = request.getOi().getY().shortValue();
                mStrShowString.struStringInfo[i].wShowStringTopLeftX = request.getOi().getX().shortValue();
                byte[] temp = osd[i].getBytes("GBK");
                mStrShowString.struStringInfo[i].wStringSize = (short) temp.length;
                System.arraycopy(temp, 0, mStrShowString.struStringInfo[i].sString, 0, temp.length);
            }
            mStrShowString.write();
            Pointer pointer = mStrShowString.getPointer();

            if (hCNetSDK.NET_DVR_SetDVRConfig(request.getCi().getUserId(), HCNetSDK.NET_DVR_SET_SHOWSTRING_V30, request.getCi().getStartChan(), pointer, mStrShowString.size())) {
                response.setCode(CameraResponse.SUCCESS_CODE);
                response.setMsg("摄像头 OSD 操作成功");
            } else {
                response.setCode(CameraResponse.FAILURE_CODE);
                response.setMsg("摄像头 OSD 操作失败：" + hCNetSDK.NET_DVR_GetLastError());
            }
        } catch (Exception ex) {
            log.error("摄像头 OSD 发生异常", ex);
            response.setCode(CameraResponse.FAILURE_CODE);
            response.setMsg("摄像头 OSD 发生异常");
            return response;
        }

        log.info(JSON.toJSONString(response));
        return response;
    }

    public CameraResponse checkCameraStatus(CameraOsdRequest request) {
        CameraResponse response = loadCameraSdk();
        if (CameraResponse.SUCCESS_CODE.equals(response.getCode())) {
            if (!hCNetSDK.NET_DVR_RemoteControl(request.getCi().getUserId(), HCNetSDK.NET_DVR_CHECK_USER_STATUS, null, 0)) {
                response.setCode(CameraResponse.FAILURE_CODE);
                response.setMsg("摄像头状态检测失败");
            } else {
                response.setMsg("摄像头状态检测成功");
            }
        }
        log.info(JSON.toJSONString(response));
        return response;
    }

}
